﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.IO;
using System.Net;
using System.Collections;
using PondConsumer;

namespace PocketPond.PondConsumer
{
    public class PondRequest
    {
        public static PocketPond.Core.Event[] getEventsToMe(String authToken)
        {
            return getEventsToMe(authToken, false);
        }

		public static PocketPond.Core.Event[] getEventsToMe( String authToken, Boolean bUnreadOnly )
		{
			List<PocketPond.Core.Event> al = new List<PocketPond.Core.Event>();

            String url = "http://services.sapo.pt/Pond/ListEventsForMeJSON?" +
						"AuthToken=" + authToken;
            if (bUnreadOnly)
            {
                url += "&OnlyUnRead=true";
            }
            String response = ExecuteGetCommand(url);

            Hashtable listPond = (System.Collections.Hashtable)JSON.JsonDecode(response);
            Hashtable listResponse = (Hashtable)listPond["Response"];
            ArrayList listEvents = (ArrayList)listResponse["Events"];

            if (listEvents == null)
            {
                return al.ToArray();
            }

			foreach ( Hashtable listItem in listEvents )
			{
				Hashtable listEvent = (Hashtable)listItem["Event"];
				PocketPond.Core.Event ev = new PocketPond.Core.Event();
				ev.AuthorName = listEvent["Name"].ToString();
				ev.AuthorId = listEvent["AuthorID"].ToString();
				ev.AuthorScreenName = listEvent["AuthorScreenName"].ToString();
				ev.AvatarUrl = listEvent["AvatarURL"].ToString();
                ev.AvatarFile = Core.Utils.getPocketPondDir() + "\\avatars\\" + ev.AuthorId + ".png";
				ev.CanReply = Boolean.Parse( listEvent["CanReplyTo"].ToString() );
				ev.TruncatedData = listEvent["TruncatedData"].ToString();
				ev.EntityId = listEvent["EntityID"].ToString();
				ev.EventId = listEvent["EventID"].ToString();
				ev.Favourite = Boolean.Parse( listEvent["Favorite"].ToString() );
				ev.ForMe = Boolean.Parse( listEvent["ForMe"].ToString() );
				//ev.Link = listEvent["Link"].ToString();
				ev.Mine = Boolean.Parse( listEvent["Mine"].ToString() );
				ev.PublishedAt = DateTime.Parse( listEvent["PublishedAt"].ToString() );
				ev.Read = Boolean.Parse( listEvent["Mine"].ToString() );
				ev.RepliedTo = Boolean.Parse( listEvent["RepliedTO"].ToString() );
				ev.ServiceId = (PocketPond.Core.Types.Services)int.Parse( listEvent["ServiceID"].ToString() );

				al.Add( ev );
			}
			return al.ToArray();
		}

		public static PocketPond.Core.Event getEventDetails( String authToken, String EventID )
		{
		    
		    String url = "http://services.sapo.pt/Pond/GetEventJSON?" +
		                    "EventIDs=" + EventID + "&AuthToken=" + authToken;
		    String response = ExecuteGetCommand( url );
		    PocketPond.Core.Event ev = new PocketPond.Core.Event();

		    Hashtable listPond = (System.Collections.Hashtable)JSON.JsonDecode( response);

		    Hashtable listRespond = (Hashtable)listPond["Response"];
			ArrayList listEvents = (ArrayList)listRespond["Events"];

			foreach ( Hashtable listItem in listEvents )
			{
				
				Hashtable listEvent = (Hashtable)listItem["Event"];
				Hashtable listData = (Hashtable)listEvent["Data"];
				ev.EventId = listEvent["EventID"].ToString();
				ev.EntityId = listEvent["EntityID"].ToString();
				ev.Content = listData["Content"].ToString();
                ev.Summary = listData["Summary"].ToString();
				ev.Link = listData["Link"].ToString();
				ev.RepliedTo = Boolean.Parse( listEvent["RepliedTO"].ToString() );
				ev.PublishedAt = DateTime.Parse( listEvent["PublishedAt"].ToString() );
				ev.ServiceId = (PocketPond.Core.Types.Services)Int32.Parse( listEvent["ServiceID"].ToString() );
				ev.Favourite = Boolean.Parse( listEvent["Favorite"].ToString() );
				ev.AuthorScreenName = listEvent["AuthorScreenName"].ToString();
                ev.AuthorName = listEvent["AuthorName"].ToString();
				ev.AvatarUrl = listEvent["AvatarURL"].ToString();
                ev.AvatarFile = Core.Utils.getPocketPondDir() + "\\avatars\\" + ev.AuthorId + ".png";
				ev.Read = Boolean.Parse( listEvent["Read"].ToString() );
				ev.ForMe = Boolean.Parse( listEvent["ForMe"].ToString() );
				ev.Mine = Boolean.Parse( listEvent["Mine"].ToString() );
				ev.CanReply = Boolean.Parse( listEvent["CanReplyTo"].ToString() );
			}
			return ev;
		}

        public static String getAuthtoken(String username, String password)
        {
            String ret = null;

            String url = "https://services.sapo.pt/Pond/GetAuthTokenJSON?" +
                          "Username=" + username + "&Password=" + password;
            String response = ExecuteGetCommand( url );

            Hashtable listPond = (System.Collections.Hashtable)JSON.JsonDecode(response);
            Hashtable listResponse = (Hashtable)listPond["Response"];

            ret = listResponse["AuthToken"].ToString();

            return ret;
        }

        public static PocketPond.Core.Event[] getEventsList(string authToken)
        {
            return getEventsList(authToken, false);
        }

        public static PocketPond.Core.Event[] getEventsList(string authToken, Boolean bUnreadOnly)
        {
            List<PocketPond.Core.Event> al = new List<PocketPond.Core.Event>();

            String url = "http://services.sapo.pt/Pond/ListEventsJSON?" +
                          "AuthToken=" + authToken;
            if (bUnreadOnly)
            {
                url += "&OnlyUnRead=true";
            }
            String response = ExecuteGetCommand(url);

            Hashtable listPond = (System.Collections.Hashtable)JSON.JsonDecode(response);
            Hashtable listResponse = (Hashtable)listPond["Response"];
            ArrayList listEvents = (ArrayList)listResponse["Events"];

            if (listEvents == null)
            {
                return al.ToArray();
            }

            foreach (Hashtable listItem in listEvents)
            {
                Hashtable listEvent = (Hashtable)listItem["Event"];
                PocketPond.Core.Event ev = new PocketPond.Core.Event();
                ev.AuthorName = listEvent["Name"].ToString();
                ev.AuthorId = listEvent["AuthorID"].ToString();
                ev.AuthorScreenName = listEvent["AuthorScreenName"].ToString();
                ev.AvatarUrl = listEvent["AvatarURL"].ToString();
                ev.AvatarFile = Core.Utils.getPocketPondDir() + "\\avatars\\" + ev.AuthorId + ".png";
                ev.CanReply = Boolean.Parse(listEvent["CanReplyTo"].ToString());
                ev.TruncatedData = listEvent["TruncatedData"].ToString();
                ev.EntityId = listEvent["EntityID"].ToString();
                ev.EventId = listEvent["EventID"].ToString();
                ev.Favourite = Boolean.Parse(listEvent["Favorite"].ToString());
                ev.ForMe = Boolean.Parse(listEvent["ForMe"].ToString());
                //ev.Link = listEvent["Link"].ToString();
                ev.Mine = Boolean.Parse(listEvent["Mine"].ToString());
                ev.PublishedAt = DateTime.Parse(listEvent["PublishedAt"].ToString());
                ev.Read = Boolean.Parse(listEvent["Mine"].ToString());
                ev.RepliedTo = Boolean.Parse(listEvent["RepliedTO"].ToString());
                ev.ServiceId = (PocketPond.Core.Types.Services)int.Parse(listEvent["ServiceID"].ToString());

                al.Add(ev);
            }

            return al.ToArray();
        }

        public static PocketPond.Core.Account[] getAccountList(string authToken)
        {
            List<PocketPond.Core.Account> al = new List<PocketPond.Core.Account>();

            String url = "http://services.sapo.pt/Pond/ListAccountsJSON?" +
                          "AuthToken=" + authToken;
            String response = ExecuteGetCommand(url);

            Hashtable listPond = (System.Collections.Hashtable)JSON.JsonDecode(response);
            Hashtable listResponse = (Hashtable)listPond["Response"];
            ArrayList listEvents = (ArrayList)listResponse["Accounts"];

            foreach (Hashtable listItem in listEvents)
            {
                Hashtable listEvent = (Hashtable)listItem["Account"];
                PocketPond.Core.Account acc = new PocketPond.Core.Account();
                acc.AccountId = listEvent["AccountID"].ToString();
                acc.CanLongText = Boolean.Parse(listEvent["CanLongText"].ToString());
                acc.CanPost = Boolean.Parse(listEvent["CanPost"].ToString());
                acc.CanShortText = Boolean.Parse(listEvent["CanShortText"].ToString());
                acc.Description = listEvent["Description"].ToString();
                acc.ServiceId = (PocketPond.Core.Types.Services)int.Parse(listEvent["ServiceID"].ToString());

                al.Add(acc);
            }

            return al.ToArray();
        }

        public static String uploadImage(String authToken, String filepath)
        {
            String ret = null;

            String url = "http://uploads.pond.pt/?AuthToken=" + authToken + "&Media=image&Json=true";

            // Read file data
            FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read);
            byte[] data = new byte[fs.Length];
            fs.Read(data, 0, data.Length);
            fs.Close();

            // Generate post objects
            Dictionary<string, object> postParameters = new Dictionary<string, object>();
            postParameters.Add("file", new FormUpload.FileParameter(data, "pond.png", "doIneedThisQuestionMark"));

            // Create request and receive response
            string userAgent = "PocketPond";
            HttpWebResponse webResponse = FormUpload.MultipartFormDataPost(url, userAgent, postParameters);

            // Process response
            StreamReader responseReader = new StreamReader(webResponse.GetResponseStream());
            String response = responseReader.ReadToEnd();
            webResponse.Close();

            Hashtable listPond = (System.Collections.Hashtable)JSON.JsonDecode(response);
            if (listPond == null)
            {
                return null;
            }
            Hashtable listResponse = (Hashtable)listPond["Response"];

            ret = listResponse["Token"].ToString();

            return ret;
        }

        public static Boolean sendPost(String authToken, String accountId, String smallText,
                                       String largeText)
        {
            string dummy;
            return sendPost(authToken, accountId, smallText, largeText, null, out dummy);
        }

        public static Boolean sendPost(String authToken, String accountId, String smallText, 
                                       String largeText, String fileToken, out String punyUrl)
        {
            String ret = null;

            String url = "http://services.sapo.pt/Pond/PostEventJSON?" +
                         "AuthToken=" + authToken + "&AccountID=" + accountId;
            
            if (!string.IsNullOrEmpty(smallText))
            {
                url += "&SmallText=" + smallText;
            }
            if (!string.IsNullOrEmpty(largeText))
            {
                url += "&LargeText=" + largeText;
            }

            if (fileToken != null)
            {
                url += "&FileTokens=" + fileToken;
            }

            Uri uri = new Uri(url);
            Console.WriteLine(uri.ToString());
            String response = ExecuteGetCommand(uri.ToString());

            Hashtable listPond = (System.Collections.Hashtable)JSON.JsonDecode(response);
            if (listPond == null)
            {
                punyUrl = null;
                return false;
            }
            Hashtable listResult = (Hashtable)listPond["Result"];
            Hashtable listResponse = (Hashtable)listPond["Response"];
            if (listResponse == null)
            {
                punyUrl = null;
                return false;
            }

            ret = listResult["Status"].ToString();
            punyUrl = listResponse["PostShortURL"].ToString();

            return ret == "200";
        }

        public static Boolean sendReply(String authToken, String accountId, String smallText,
                                       String largeText, String fileToken, String replyTo, out String punyUrl)
        {
            String ret = null;
            punyUrl = null;

            String url = "http://services.sapo.pt/Pond/ReplyToEventJSON?" +
                         "AuthToken=" + authToken +
                         "&InReplyToEvent=" + replyTo; 

            if (!string.IsNullOrEmpty(smallText))
            {
                url += "&SmallText=" + smallText;
            }
            if (!string.IsNullOrEmpty(largeText))
            {
                url += "&LargeText=" + largeText;
            }
                         
            if (fileToken != null)
            {
                url += "&FileTokens=" + fileToken;
            }

            Uri uri = new Uri(url);
            Console.WriteLine(uri.ToString());
            String response = ExecuteGetCommand(uri.ToString());

            Hashtable listPond = (System.Collections.Hashtable)JSON.JsonDecode(response);
            if (listPond == null)
            {
                return false;
            }
            Hashtable listResult = (Hashtable)listPond["Result"];
            Hashtable listResponse = (Hashtable)listPond["Response"];

            ret = listResult["Status"].ToString();
            if (listResponse != null)
            {
                punyUrl = listResponse["PostShortURL"].ToString();
            }

            return ret == "200";
        }

        public static Boolean setEventRead(String authToken, Boolean bRead, String[] eventIds )
        {
            String ret = null;

            String url = "http://services.sapo.pt/Pond/SetEventReadJSON?" +
                          "AuthToken=" + authToken +
                          "&Read=" + (bRead ? "true" : "false") + 
                          "&EventIDs=";
            for (int n = 0; n < eventIds.Count(); n++)
            {
                url += eventIds[n];
                if (n < eventIds.Count() - 1)
                {
                    url += "+";
                }
            }

            String response = ExecuteGetCommand(url);

            Hashtable listPond = (System.Collections.Hashtable)JSON.JsonDecode(response);
            Hashtable listResult = (Hashtable)listPond["Result"];

            ret = listResult["Status"].ToString();

            return ret == "200";
        }

        protected static string ExecuteGetCommand(string url)
        {
            HttpWebRequest client = (HttpWebRequest)WebRequest.Create(url);//WebRequestFactory.CreateHttpRequest(url);
            client.Timeout = 20000;

            try
            {
                using (HttpWebResponse httpResponse = (HttpWebResponse)client.GetResponse())
                {
                    using (Stream stream = httpResponse.GetResponseStream())
                    {
                        using (StreamReader reader = new StreamReader(stream))
                        {
                            return reader.ReadToEnd();
                        }
                    }
                }
            }
            catch (WebException ex)
            {
                //PockeTwit.GlobalEventHandler.LogCommError(ex);
                //
                // Handle HTTP 404 errors gracefully and return a null string to indicate there is no content.
                //
                if (ex.Response is HttpWebResponse)
                {
                    try
                    {
                        if ((ex.Response as HttpWebResponse).StatusCode == HttpStatusCode.NotFound)
                        {
                            return null;
                        }

                        HttpWebResponse errorResponse = (HttpWebResponse)ex.Response;
                        if (errorResponse.StatusCode == HttpStatusCode.Unauthorized)
                        {
                            return null;
                        }
                        string ErrorText;
                        using (Stream stream = errorResponse.GetResponseStream())
                        {
                            using (StreamReader reader = new StreamReader(stream))
                            {
                                ErrorText = reader.ReadToEnd();
                                XmlDocument doc = new XmlDocument();
                                doc.LoadXml(ErrorText);

                                if (doc.SelectSingleNode("//error").InnerText.StartsWith("Rate limit exceeded"))
                                {
                                    DateTime NewTime = DateTime.Now;
                                    errorResponse.Close();
                                    throw new Exception("Timeout until " + NewTime.ToString());
                                }
                                else
                                {
                                    Exception TwitterError = new Exception(doc.SelectSingleNode("//error").InnerText);
                                    throw TwitterError;
                                }
                            }
                        }
                    }
                    catch
                    {
                        ex.Response.Close();

                    }


                }

            }
            return null;
        }

        protected static string ExecutePostCommand(string url)
        {
            HttpWebRequest client = WebRequestFactory.CreateHttpRequest(url);
            client.Timeout = 20000;

            try
            {
                using (HttpWebResponse httpResponse = (HttpWebResponse)client.GetResponse())
                {
                    using (Stream stream = httpResponse.GetResponseStream())
                    {
                        using (StreamReader reader = new StreamReader(stream))
                        {
                            return reader.ReadToEnd();
                        }
                    }
                }
            }
            catch (WebException ex)
            {
                //PockeTwit.GlobalEventHandler.LogCommError(ex);
                //
                // Handle HTTP 404 errors gracefully and return a null string to indicate there is no content.
                //
                if (ex.Response is HttpWebResponse)
                {
                    try
                    {
                        if ((ex.Response as HttpWebResponse).StatusCode == HttpStatusCode.NotFound)
                        {
                            return null;
                        }

                        HttpWebResponse errorResponse = (HttpWebResponse)ex.Response;
                        if (errorResponse.StatusCode == HttpStatusCode.Unauthorized)
                        {
                            return null;
                        }
                        string ErrorText;
                        using (Stream stream = errorResponse.GetResponseStream())
                        {
                            using (StreamReader reader = new StreamReader(stream))
                            {
                                ErrorText = reader.ReadToEnd();
                                XmlDocument doc = new XmlDocument();
                                doc.LoadXml(ErrorText);

                                if (doc.SelectSingleNode("//error").InnerText.StartsWith("Rate limit exceeded"))
                                {
                                    DateTime NewTime = DateTime.Now;
                                    errorResponse.Close();
                                    throw new Exception("Timeout until " + NewTime.ToString());
                                }
                                else
                                {
                                    Exception TwitterError = new Exception(doc.SelectSingleNode("//error").InnerText);
                                    throw TwitterError;
                                }
                            }
                        }
                    }
                    catch
                    {
                        ex.Response.Close();

                    }


                }

            }
            return null;
        }

    }
}
